# coding=utf-8
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QTableWidgetItem, QAbstractItemView
from PyQt5.QtCore import *
from PyQt5.QtGui import QPixmap, QColor, QIcon
# from ctypes import *
from PyQt5 import QtCore
import math
# import pyqtgraph as pg
# import numpy as np
# import matplotlib.pyplot as plt

import xlwt
import sqlite3
import time
from threading import Timer, Thread
from datetime import datetime
import random

from lib.share import ShareInfo
from lib.final import FinalList
# SCD中有输出打印，方便调试
# from SCDDemo.SCD import CropDetc2
# 打包时使用Release版本
# from SCDDemo.SCDRelease import CropDetc2
from SCDDemo.ShortCircuit_ZhuyeZinc import CropDetc2
# from SCDDemo.SCD2 import CropDetc2

# 单独考虑裸露板的版本
# from SCDDemo.SCD4 import CropDetc2

# from WinUi.CheckingUI import Ui_Checking
from WinUi.RealPlayUI import Ui_MainWindow
from WinUi.LoginUI import Ui_LoginPage
from NetSDK.NetSDK import NetClient
from NetSDK.SDK_Struct import *
from NetSDK.SDK_Callback import fDisConnect, fHaveReConnect, fDecCBFun, fRealDataCallBackEx2, CB_FUNCTYPE
from NetSDK.SDK_Enum import SDK_RealPlayType, EM_LOGIN_SPAC_CAP_TYPE, EM_REALDATA_FLAG, EM_QUERY_DEV_INFO_TYPE
from NetSDK.SDK_Struct import C_LLONG, sys_platform, NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY, NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY

PATH = 'C:/RealPlayZinc/'

# 当前截图的路径
NowPicturePath = []


# 抓图回调
@CB_FUNCTYPE(None, C_LLONG, POINTER(c_ubyte), c_uint, c_uint, C_DWORD, C_LDWORD)
def CaptureCallBack(lLoginID,pBuf,RevLen,EncodeType,CmdSerial,dwUser):
    if lLoginID == 0:
        return
    print('Enter CaptureCallBack')
    ShareInfo.MyMainWindow.update_ui(pBuf, RevLen, EncodeType)

class Runthread(QtCore.QThread):
    #  通过类成员对象定义信号对象
    # _signal = pyqtSignal(str)

    def __init__(self):
        super(Runthread, self).__init__()

    def __del__(self):
        self.wait()

    def run(self):
        # # 加入提示框就会卡死
        ShareInfo.MyMainWindow.Prompt.setText('正在检测——请勿操作！请耐心等待30秒！')
        # self.Prompt.setStyleSheet("background-color:rgb(255,0,0);\n"
        #                           "border-radius: 5px;  \n"
        #                           "        border: 1px gray;\n"
        #                           "        color: white;\n"
        #                           "        border-style: outset;")
        ShareInfo.MyMainWindow.Prompt.repaint()
        time.sleep(0.5)



# 登录窗口
class MyLogin(QMainWindow,Ui_LoginPage):
    def __init__(self, parent=None):
        super(MyLogin, self).__init__(parent)
        self.setupUi(self)

        # 界面初始化
        self._init_ui()
    def _init_ui(self):
        self.setWindowIcon(QIcon(PATH + 'css/logo-red.jpeg'))
        pix1 = QPixmap(PATH + 'css/logo1.png')
        self.logo1.setPixmap(pix1)
        # 按照Qlabel尺寸显示图片
        self.logo1.setScaledContents(True)
        # pix2 = QPixmap(PATH + 'css/logo2.png')
        # self.logo2.setPixmap(pix2)
        # # 按照Qlabel尺寸显示图片
        # self.logo2.setScaledContents(True)
        self.login_btn.clicked.connect(self.login_btn_onclick)
        self.login_password.returnPressed.connect(self.login_btn_onclick)

    def login_btn_onclick(self):
        username = self.login_username.text()
        password = self.login_password.text()
        if username == 'admin' and password == 'admin123':
            print('登录成功')
            self.close()
            ShareInfo.MyMainWindow = MyMainWindow()
            ShareInfo.MyMainWindow.show()
        else:
            QMessageBox.warning(self,'登录失败','请确认用户名和密码是否正确!')

class myobject(QObject):
    def timerEvent(self, evt):   #重写对象的定时器函数
        # SnapFre = int(self.SnapFre_lineEdit.text())
        ShareInfo.MyMainWindow.Check_1_onclick() # 此处不是self，而是需要调用MyMainWindow的方法
        # print(evt,'1')

# 主界面
class MyMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.LoginFlag = False  # 登录成功标志
        # 界面初始化
        self._init_ui()

        # NetSDK用到的相关变量和回调
        self.loginID = C_LLONG()
        self.playID = C_LLONG()
        self.freePort = c_int()
        self.m_DisConnectCallBack = fDisConnect(self.DisConnectCallBack)
        self.m_ReConnectCallBack = fHaveReConnect(self.ReConnectCallBack)
        self.m_DecodingCallBack = fDecCBFun(self.DecodingCallBack)
        self.m_RealDataCallBack = fRealDataCallBackEx2(self.RealDataCallBack)

        # 获取NetSDK对象并初始化
        self.sdk = NetClient()
        self.sdk.InitEx(self.m_DisConnectCallBack)
        self.sdk.SetAutoReconnect(self.m_ReConnectCallBack)

        # 回传的数据用字典展示
        self.DICT = {}

        # 自动检测标志
        self.checkFlag = 0

        # 全场景的最高温和最低温
        self.maxT = 0
        self.minT = 0

        # 打印标志位，每检测20次，自动打印一次
        # self.printFlag = 0

        # 报警颜色
        self.QColorList = [QColor(255, 255, 255), QColor(255, 211, 155), QColor(255, 48, 48), QColor(139, 26, 26)]

        #     手动设定的阈值温度
        # 裸露板的温度阈值
        self.uncovT1 = 230
        self.uncovT2 = 240
        self.uncovT3 = 250
        # 高低温兜底限制
        # self.allMaxT = int(self.allmax.text())
        # self.allMinT = int(self.allmin.text())

        self.parmList = [4.5,3.5,2.5]

        self.SnapFreTmp = 0

        self.temp1 = []
        self.temp2 = []
        self.temp3 = []
        self.obj = myobject(self)

    # 初始化界面
    def _init_ui(self):
        self.plot1.setBackground('w')
        self.setWindowIcon(QIcon(PATH + 'css/logo-red.jpeg'))
        pix = QPixmap(PATH + 'css/logo1.png')
        self.logo.setPixmap(pix)
        # 按照Qlabel尺寸显示图片
        self.logo.setScaledContents(True)

        # 设置标签栏的图标和字体
        # self.tabWidget.setFont()
        self.tabWidget.setTabIcon(0,QIcon(PATH + 'css/tab/fdj.ico'))
        self.tabWidget.setTabIcon(1, QIcon(PATH + 'css/tab/set.ico'))
        self.tabWidget.setTabIcon(2, QIcon(PATH + 'css/tab/log.ico'))
        self.tabWidget.setTabIcon(3, QIcon(PATH + 'css/tab/more.ico'))

        self.login_btn.setText('连接')
        self.play_btn.setText('监视(Play)')
        self.play_btn.setEnabled(False)

        self.localInfoEdit.setText('C:\\RealPlayDemo\\css\\test.jpg')
        self.IP_lineEdit.setText('192.168.1.108')
        self.Port_lineEdit.setText('37777')
        # self.Name_lineEdit.setText('admin')
        # self.Pwd_lineEdit.setText('admin123')

        # 显示实时时间
        timer = QTimer(self)
        timer.timeout.connect(self.showtime)
        timer.start()

        self.tablePrompt1.setText("请单击表格显示故障详情")
        self.tablePrompt2.setText("无详情显示")

        # 日期预设为当前日期
        self.dateStart.setDate(QDate.currentDate())
        self.dateEnd.setDate(QDate.currentDate())

        self.setWindowFlag(Qt.WindowMinimizeButtonHint)
        self.setWindowFlag(Qt.WindowCloseButtonHint)
        # self.setFixedSize(self.width(), self.height())
        # todo
        # 登录->连接
        self.login_btn.clicked.connect(self.login_btn_onclick)
        self.play_btn.clicked.connect(self.play_btn_onclick)
        self.Check_1.clicked.connect(self.Check_1_onclick)

        self.Check_2.clicked.connect(self.Check_2_onclick)

        self.Check_3.clicked.connect(self.Check_3_onclick)
        self.login_out_btn.clicked.connect(self.login_out_btn_onclick)
        self.snapSure.clicked.connect(self.snapSure_onclick)
        self.print_btn.clicked.connect(self.print_btn_onclick)
        self.suggest_btn.clicked.connect(self.suggest_btn_onclick)
        self.choice_btn.clicked.connect(self.choice_btn_onclick)
        self.output_btn.clicked.connect(self.output_btn_onclick)

        # 测试按钮(刷新按钮)
        self.test111.clicked.connect(self.test111_onclick)
        self.PlayMode_comboBox.addItem('CallBack')
        if sys_platform == 'windows':
            self.PlayMode_comboBox.addItem('PlaySDK')

        self.table.clicked.connect(self.item_onclick)

    def showtime(self):
        datetime = QDateTime.currentDateTime()
        text = datetime.toString()
        self.curTime.setText(" " + text)

    def plotfunc1(self):
        if len(self.temp1) <= 0:
            pass

        # print(self.temp3)

        # self.plot1.setBackground('w')
        # self.plot1.plot(hour, t)
        self.plot1.clear()
        self.plot1.addLegend()
        self.plot1.plot(self.temp1, pen=(255, 0, 0), name="槽面均温")
        self.plot1.plot(self.temp2, pen=(0, 255, 0), name="铜排温度")
        self.plot1.plot(self.temp3, pen=(0, 0, 255), name="出液口温")

        self.plot1.setLabel('left', '温度')
        self.plot1.setLabel('bottom', '监测时间')






        # # 创建 PlotWidget 对象
        # self.pw = pg.PlotWidget()
        #
        # # 设置图表标题
        # self.pw.setTitle("气温趋势", color='008080', size='12pt')
        #
        # # 设置上下左右的label
        # self.pw.setLabel("left", "气温(摄氏度)")
        # self.pw.setLabel("bottom", "时间")
        # # 背景色改为白色
        # self.pw.setBackground('w')
        #
        # hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        # temperature = [30, 32, 34, 32, 33, 31, 29, 32, 35, 45]
        #
        # # hour 和 temperature 分别是 : x, y 轴上的值
        # self.pw.plot(hour,
        #              temperature,
        #              pen=pg.mkPen('b')  # 线条颜色
        #              )
        #
        # # 垂直layout里面放 pyqtgraph图表控件 和 前面的水平layout
        # vbox = self.QVBoxLayout()
        # vbox.addWidget(self.pw)
        # # vbox.addLayout(hbox)

    def output_btn_onclick(self):
        cx = sqlite3.connect('C:/RealPlayZinc/DataBase/temp.db')
        cu = cx.cursor()
        print("temedata2数据库连接成功!")

        # 查询最新的数据
        sql = "select * from tempdata2 order by id DESC limit 16 "
        data = cu.execute(sql)
        self.plainTextEdit.clear()
        self.plainTextEdit.appendPlainText('槽号  均温   铜排  出液口       时间')
        for d in data:
            self.plainTextEdit.appendPlainText(' ' + '  |  '.join(str(i) for i in d[1:]))

        # 写入txt和excel文件中
        nowtime = datetime.now().strftime('%Y%m%d_%H%M%S_')
        filename = 'C:/RealPlayZinc/TempLog/' + nowtime + 'tempLog.txt'
        f = open(filename, 'a', encoding='gb2312')
        # 保存日志
        text = self.plainTextEdit.toPlainText()
        f.write(text)
        f.close()

        workbook = xlwt.Workbook()
        sheet = workbook.add_sheet("Sheet")
        # 注意，每次查询到的数据只能使用一次
        sql = "select * from tempdata2 order by id DESC limit 16 "
        data = cu.execute(sql)
        i, j = 1, 0
        sheetColName = ['槽号', '均温', '铜排', '出液口', '时间']
        for x in range(5):
            sheet.write(0, x, sheetColName[x])
        for d in data:
            for dd in d[1:]:
                sheet.write(i, j, str(dd))
                j += 1
            i += 1
            j = 0

        workbook.save("C:/RealPlayZinc/TempLog/"+ nowtime + "tempLog.xls")

        cx.close()



    def choice_btn_onclick(self):
        # 显示所有槽
        allCell = int(self.checkBox1.checkState())
        # 仅显示异常数据
        justShowExct = int(self.checkBox2.checkState())
        # 屏蔽行车数据
        justCell = int(self.checkBox3.checkState())
        # 极板编号
        num = self.Number.text()
        dateStart = self.dateStart.text()
        dateEnd = self.dateEnd.text()
        startId, endId = 0, 0
        # print(dateStart, dateEnd)


        # 异常温度阈值
        copTh = self.copth.text()
        outTh = self.outth.text()

        cx = sqlite3.connect('C:/RealPlayZinc/DataBase/temp.db')
        cu = cx.cursor()
        print("temedata2数据库连接成功!")

        # startId预设为1407(数据库的第一条记录)，endId预设为最后一条记录的id
        # 防止日期输入错误导致查询失败
        startId = 1407
        sql = "select id from tempdata2 order by id DESC limit 1 "
        data = cu.execute(sql)
        for i in data:
            endId = i[0]


        # 根据输入的起始和结束日期查到对应的id
        sql = "select id from tempdata2 where date like" + "'" + dateStart + "%' limit 1"
        id = cu.execute(sql)
        for i in id:
            startId = i[0]
            print(startId)

        sql = "select id from tempdata2 where date like" + "'" + dateEnd + "%' order by id DESC limit 1"
        id = cu.execute(sql)
        for i in id:
            endId = i[0]
            # print(endId)

        # print(startId, endId)
        #根据起始、结束id和电解槽编号查询到温度
        cnt = 0
        if allCell == 0:
            if justShowExct == 0:
                if justCell == 0:  # 不屏蔽行车数据
                    sql = "select * from tempdata2 where id >= " + str(startId) + " and id <= " + str(
                        endId) + " and loc = " + str(num)
                else:
                    sql = "select * from tempdata2 where id >= " + str(startId) + " and id <= " + str(
                        endId) + " and loc = " + str(num) + " and temp1 > 26"
                data = cu.execute(sql)
                self.temp1 = []
                self.temp2 = []
                self.temp3 = []
                self.plainTextEdit.clear()
                self.plainTextEdit.appendPlainText('槽号  均温   铜排  出液口       时间')
                for d in data:
                    self.plainTextEdit.appendPlainText(' ' + '  |  '.join(str(i) for i in d[1:]))
                    self.temp1.append(d[2])
                    self.temp2.append(d[3])
                    self.temp3.append(d[4])
                    cnt += 1
            else:
                sql = "select * from tempdata2 where id >= " + str(startId) + " and id <= " + str(
                    endId) + " and loc = " + str(num) + " and ( temp2 > " + copTh + " or temp3 > " + outTh + ")"
                data = cu.execute(sql)
                self.plainTextEdit.clear()
                self.plainTextEdit.appendPlainText('槽号  均温   铜排  出液口       时间')
                for d in data:
                    self.plainTextEdit.appendPlainText(' ' + '  |  '.join(str(i) for i in d[1:]))
                    cnt += 1
        else:
            if justShowExct == 0:
                sql = "select * from tempdata2 where id >= " + str(startId) + " and id <= " + str(
                    endId)
            else:
                # 暂时将铜排温度超过40设为异常
                sql = "select * from tempdata2 where id >= " + str(startId) + " and id <= " + str(
                    endId) + " and temp2 > 40"
            data = cu.execute(sql)
            self.plainTextEdit.clear()
            self.plainTextEdit.appendPlainText('槽号  均温   铜排  出液口       时间')
            for d in data:
                self.plainTextEdit.appendPlainText(' ' + '  |  '.join(str(i) for i in d[1:]))
                cnt += 1

        self.plainTextEdit.appendPlainText('共检索到' + str(cnt) + '条数据！')

        # cx.commit()
        cx.close()

    def print_btn_onclick(self):
        f = open('log.txt','a',encoding='gb2312')
        # 保存日志
        text = self.plainTextEdit.toPlainText()
        f.write(text)
        f.close()
        self.plainTextEdit.clear()
        self.plainTextEdit.appendPlainText('\n日志已经保存！./log.txt\n')


    def suggest_btn_onclick(self):
        f = open('suggest.txt', 'a', encoding='gb2312')
        # 保存日志
        text = self.suggestTextEdit.toPlainText()
        f.write(text)
        f.write('\n')
        f.close()
        self.suggestTextEdit.clear()
        self.suggestTextEdit.appendPlainText('文本已提交，谢谢\n')

    # 测试按钮（刷新）
    def test111_onclick(self):
        # print(self.query_dev_info())
        # cb = CheckBoard()
        # no,list= cb.MyCheck()
        # print(no);
        # for i in list:
        #     print(i)
        self.plotfunc1()
        pass

    def getParm(self,path,parmList):
        #     获取对象
        #     调用方法
        cd = CropDetc2()
        dot = [[260.435578330893, 335.586383601757], [1017.56588579795, 319.094436310395],
               [219.955344070278, 603.955344070278], [1094.02855051245, 576.968521229868]]

        self.DICT = cd.MyCheck(path, dot, parmList, self.minT, self.maxT)
        # self.DICT = cd.MyCheck(path,parmList)
        # print(self.DICT)
        # self.DICT = cd.MyCheck(path)
        # self.DICT = {'1-1':[2,4,5,65,2],'1-2':[2,4,6,7]}

    # table单击事件（绑定到table上）
    def item_onclick(self, index):
        table_column = index.column()
        table_row = index.row()
        current_item = self.table.item(table_row, table_column)
        current_widget = self.table.cellWidget(table_row, table_column)
        print(str(table_row + 1) + '列,' + str(table_column+1) + '槽')
        self.tablePrompt1.setText("已选中：" + str(table_row + 1) + '列' + str(table_column+7) + '槽')
        self.tablePrompt2.setText("正在显示" + str(table_row + 1) + '列' + str(table_column+7) + '槽的故障详情')
        # 当前只有部分槽可检测！
        if table_row > 1 or table_column > 8:
            return
        # 标色
        self.table2.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 背景色重置为透明，无法一次性全部重置
        for i in range(0, 30):
            self.table2.setItem(0, i, QTableWidgetItem().setBackground(QColor(255, 255, 255)))
            self.table3.setItem(0, i, QTableWidgetItem().setBackground(QColor(255, 255, 255)))

        if len(self.DICT) > 0:
            string = str(table_row + 1) + '-' + str(table_column + 7)
            # 将两个置空的槽排除
            if string == '2-7' or string == '2-15':
                return
            staList = self.DICT[string]

            for i in range(len(staList)):
                sta = staList[i]
                if sta == 0:
                    continue

                # 此处使用单例模式会报错
                cellItem = QTableWidgetItem()
                cellItem.setBackground(self.QColorList[sta])
                if i < 30:
                    self.table2.setItem(0, i, cellItem)
                else:
                    self.table3.setItem(0, i - 30, cellItem)

        else:
            return

    # 截图保存和显示
    def update_ui(self, pBuf, RevLen, EncodeType):
        pic_buf = cast(pBuf, POINTER(c_ubyte*RevLen)).contents
        # pic_buf = PATH + 'css/11.jpg'

        # exe文件需要和snap文件夹在同一级
        nowtime = datetime.now().strftime('%Y%m%d_%H%M%S_')
        name = nowtime + '_' + str(self.maxT) + '_' + str(self.minT)
        with open(PATH + '/Snap/capture' + name +'.jpg', 'wb+') as f:
            f.write(pic_buf)
        # 参数：图片地址
        NowPicturePath.insert(0, PATH + 'Snap/capture' + name + '.jpg')
        print(NowPicturePath[0])
        # self.getParm(self.NowPicturePath)  # 执行后就获取到全局DICT

    # 检测程序——手动
    def Check_1_onclick(self):
        # 设置抓图回调
        if self.LoginFlag:
            self.Check_1.setText('正在检测')
            # 设置为强制刷新，不然会等到程序执行完了才显示quer
            self.Check_1.repaint()
            # 获取全图中最高温和最低温
            # self.maxT, self.minT = self.query_dev_info()
            self.maxT, self.minT = 0, 0

            # 开始截图
            dwUser = 0
            self.sdk.SetSnapRevCallBack(CaptureCallBack, dwUser)
            channel = self.Channel_comboBox.currentIndex()
            snap = SNAP_PARAMS()
            snap.Channel = channel
            snap.Quality = 1
            snap.mode = 0
            # 抓图

            self.sdk.SnapPictureEx(self.loginID, snap)

            # todo  暂时不用检测
            self.thread = Runthread()
            # 开始线程
            self.thread.start()

            self.checkThread()

            self.getTemp()

            self.Check_1.setText('手动检测')

            self.tablePrompt2.setText("无详情显示")

        else:
            self.warningBox()

    def getTemp(self):
        getAvgTemp = self.query_dev_info2(FinalList.AvgX, FinalList.AvgY)
        getCopTemp = self.query_dev_info2(FinalList.CopX, FinalList.CopY)
        getOutTemp = self.query_dev_info2(FinalList.OutX, FinalList.OutY)
        cx = sqlite3.connect('C:/RealPlayZinc/DataBase/temp.db')
        cu = cx.cursor()
        print("数据库连接成功!")
        for i in range(len(getAvgTemp)):
            cu.execute("insert into tempdata2 (loc,temp1, temp2, temp3, date) VALUES(?,?,?,?,?)", (i, int((getAvgTemp[i] + getCopTemp[i])/2), getCopTemp[i] + 4, getOutTemp[i] + 6, datetime.now().strftime('%Y/%m/%d %H-%M-%S')))

        cx.commit()
        cx.close()
        for i in range(len(getAvgTemp)):
            getAvgTemp[i] = int((getAvgTemp[i] + getCopTemp[i])/2)
            getCopTemp[i] = getCopTemp[i] + 4
            getOutTemp[i] = getOutTemp[i] + 6

        tempSet = [getAvgTemp, getCopTemp, getOutTemp]
        # print(tempSet)
        self.showTemp(tempSet)


    def showTemp(self, tempSet):
        for i in range(0, 3):
            for j in range(9):
                newItem = QTableWidgetItem("")
                newItem.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                newItem.setText(str(tempSet[i][j]))

                self.table4.setItem(i, j, newItem)
        for i in range(3, 6):
            for j in range(1,8):
                newItem = QTableWidgetItem("")
                newItem.setText(str(tempSet[i-3][j+8]))
                newItem.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.table4.setItem(i, j, newItem)


    # 检测子线程
    def checkThread(self):
        # self.Prompt.setText('正在检测——请勿操作！请耐心等待30秒！')
        # self.Prompt.setStyleSheet("background-color:rgb(255,0,0);\n"
        #                           "border-radius: 5px;  \n"
        #                           "        border: 1px gray;\n"
        #                           "        color: white;\n"
        #                           "        border-style: outset;")
        # self.Prompt.repaint()
        # time.sleep(2)

        nowtime = datetime.now().strftime('************%Y-%m-%d ************ %H:%M:%S************')
        self.plainTextEdit.appendPlainText(nowtime)
        # !!!!!!!!千万不能立即执行，因为此时路径还未生成
        time.sleep(1)
        self.plainTextEdit.appendPlainText('图片保存路径为：' + str(NowPicturePath[0]))
        checkThread = Thread(
            target=self.getParm,
            args=(NowPicturePath[0], self.parmList,)
        )
        # 获取到数据之后（DICT已经更新）进行：
        
        checkThread.start()
        checkThread.join()



        print('子线程执行完毕，接收DCIT完毕……')
        # ShareInfo.MyMainWindow.raise_()


        image = QPixmap(PATH + 'SHOW.jpg').scaled(self.PicSnap.width(), self.PicSnap.height())
        self.PicSnap.setPixmap(image)

        nowtime = datetime.now().strftime('%Y-%m-%d * %H:%M:%S')
        self.Prompt.setText('检测完毕——' + str(nowtime))
        # self.Prompt.setStyleSheet("background-color:rgb(240,255,255);\n"
        #                           "border-radius: 5px;  \n"
        #                           "        border: 1px gray;\n"
        #                           "        border-style: outset;")

        # 检测完毕，开始渲染
        # c 是行  r 是列
        for NO in self.DICT.keys():
            c = int(NO[0])
            r = int(NO[2:])
            staList = self.DICT[NO]

            maxSta = max(staList)
            self.startCheck(c - 1, r - 7, maxSta)

        # 数据渲染完成更新两个表格
        self.table.viewport().update()
        self.table2.clear()

        # todo 可能卡死
        # self.printFlag += 1
        # if self.printFlag == 20:
        #     self.printFlag = 0
        #     self.print_btn_onclick()

    # 离线检测
    def Check_3_onclick(self):
        localInfo = str(self.localInfoEdit.text())
        print(localInfo)
        NowPicturePath.insert(0, localInfo)
        self.checkThread()

    # 警告框
    def warningBox(self):
        reply = QMessageBox.warning(self, '警告', '请先连接设备！', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            return
        else:
            self.LoginFlag = False
            self.close()
            ShareInfo.MyLogin = MyLogin()
            ShareInfo.MyLogin.show()

    # 自动检测——点击自动检测，调用startCheck开始检测（开启新线程！）
    def Check_2_onclick(self):
        # 先和Check_1一样，截图按钮确定之后，就调用Check_1
        if self.LoginFlag == False:
            self.warningBox()
            return

        SnapFre = int(self.SnapFre_lineEdit.text()) * 60000
        if self.checkFlag == 0:
            self.checkFlag = 1
            self.Check_2.setText('自检已开')
            self.Check_2.repaint()
            self.Check_1_onclick()
            self.id = self.obj.startTimer(SnapFre)
            print("自检线程id:" + str(self.id))
        else:
            self.checkFlag = 0
            self.Check_2.setText('自动检测')
            self.Check_2.repaint()
            self.obj.killTimer(self.id)
            # self.t.cancel()

    def printTimer(self):
        # 57分钟保存一次日志
        logFre = 57 + random.randint(0,3)
        t = Timer(logFre * 60 + random.randint(35,45), self.printTimer)
        if self.LoginFlag:
            t.start()
            self.print_btn_onclick()
        else:
            t.cancel()
            return


    # todo
    # 将t作为一个对象，保证单一性
    def snapTimer(self):
        SnapFre = int(self.SnapFre_lineEdit.text())
        if self.SnapFreTmp != SnapFre or self.checkFlag == 0:
            self.t.cancel()
        self.SnapFreTmp = SnapFre
        self.t = Timer(SnapFre * 60, self.snapTimer)
        print(self.t)
        # print(self.LoginFlag)
        # 此处修改还没验证
        if self.LoginFlag and SnapFre != 0 and self.checkFlag == 1:
            # print(self.LoginFlag)

            print('TimeNow:%s' % (datetime.now().strftime('%Y-%m-%d %H:%M:%S')))

            self.Check_1_onclick()
            self.t.start()
        else:
            self.t.cancel()
            return

    # 设置页面的确认键
    def snapSure_onclick(self):

        p3 = int(self.p3.text()) / 20
        p2 = int(self.p2.text()) / 20
        p1 = int(self.p1.text()) / 20
        print(p3)

        # self.allMinT = int(self.allmin.text())
        # self.allMaxT = int(self.allmax.text())

        self.parmList = [p3, p2, p1]

    # c为行，r为列，sta为状态（严重故障3，一般故障2，疑似故障1，正常0，不显示不处理不记录）
    def startCheck(self,c,r,sta):
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        newItem = QTableWidgetItem("")
        newItem.setBackground(self.QColorList[sta])
        self.table.setItem(c, r, newItem)
        # 新增日志代码 @2021/7/11/21/49/22
        # todo
        # 按照标准格式存入数据库，便于读写搜索
        nowtime = datetime.now().strftime('%Y-%m-%d ** %H:%M:%S')

        staList = self.DICT[str(c+1) + '-' + str(r+7)]
        faultList = ['疑似故障', '一般故障', '严重故障']
        for i in range(len(staList)):
            staB = staList[i]
            if staB == 0:
                continue
            else:
                self.plainTextEdit.appendPlainText(str(c + 1) + '列' + (str(r + 7)).zfill(2) + '槽【' + (str(i + 1)).zfill(
                    2) + '】号板' + '----' + faultList[staB - 1] + '----' + nowtime)

    # 获取全图的最低最高温
    def query_dev_info(self):
        inGetTemper = NET_IN_RADIOMETRY_GETTEMPER()
        inGetTemper.dwSize = sizeof(NET_IN_RADIOMETRY_GETTEMPER)
        inGetTemper.stCondition = NET_RADIOMETRY_CONDITION()
        inGetTemper.stCondition.nPresetId = 0
        # 规则编号
        inGetTemper.stCondition.nRuleId = 1
        inGetTemper.stCondition.nMeterType = 3
        inGetTemper.stCondition.szName = str.encode('rb1')
        inGetTemper.stCondition.nChannel = 0
        outGetTemper = NET_OUT_RADIOMETRY_GETTEMPER()
        outGetTemper.dwSize = sizeof(NET_OUT_RADIOMETRY_GETTEMPER)
        result = self.sdk.QueryDevInfo(self.loginID, EM_QUERY_DEV_INFO_TYPE.NET_QUERY_DEV_RADIOMETRY_TEMPER, inGetTemper, outGetTemper, None, 5000)
        if result == 1:
            return int(outGetTemper.stTempInfo.fTemperMax), int(outGetTemper.stTempInfo.fTemperMin)
            # print("获取测温参数成功（QueryDevInfo succeed).")
            # print("温度(temperature):%.2f; 最高温度(Maximum temperature):%.2f;最低温度(lowest temperature):%.2f" % (outGetTemper.stTempInfo.fTemperAver, outGetTemper.stTempInfo.fTemperMax, outGetTemper.stTempInfo.fTemperMin))
        else:
            print("获取测温参数失败（QueryDevInfo failed)." + str(self.sdk.GetLastErrorMessage()))

    def query_dev_info2(self, x, y):
            temp = []
            inTemper = NET_IN_RADIOMETRY_GETPOINTTEMPER()
            inTemper.dwSize = sizeof(NET_IN_RADIOMETRY_GETPOINTTEMPER)
            outTemper = NET_OUT_RADIOMETRY_GETPOINTTEMPER()
            outTemper.dwSize = sizeof(NET_OUT_RADIOMETRY_GETPOINTTEMPER)
            inTemper.nChannel = 0
            for i in range(0, 16):
                # 1280*1080对应上8192坐标系
                inTemper.stCoordinate.nx = int(x[i] * 6.4)
                inTemper.stCoordinate.ny = int(y[i] * 8)
                try:
                    result = self.sdk.QueryDevInfo(self.loginID, EM_QUERY_DEV_INFO_TYPE.RADIOMETRY_POINT_TEMPER,
                                                   inTemper,
                                                   outTemper, None, 5000)
                except Exception as e:
                    print(e)

                if result:
                    # print("点温度(temperature):%.2f" % (outTemper.stPointTempInfo.fTemperAver))
                    temp.append(math.floor(outTemper.stPointTempInfo.fTemperAver))
                else:
                    print("获取测温参数失败1（QueryDevInfo failed)." + str(self.sdk.GetLastError()))
                    break
            # print(temp)


            return temp
    def login_btn_onclick(self):
        if not self.loginID:
            # ip和端口手动输入，用户名和密码暂时固定！
            ip = self.IP_lineEdit.text()
            port = int(self.Port_lineEdit.text())
            username = 'admin'
            password = 'admin123'

            stuInParam = NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY()
            stuInParam.dwSize = sizeof(NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY)
            stuInParam.szIP = ip.encode()
            stuInParam.nPort = port
            stuInParam.szUserName = username.encode()
            stuInParam.szPassword = password.encode()
            stuInParam.emSpecCap = EM_LOGIN_SPAC_CAP_TYPE.TCP
            stuInParam.pCapParam = None

            stuOutParam = NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY()
            stuOutParam.dwSize = sizeof(NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY)

            self.loginID, device_info, error_msg = self.sdk.LoginWithHighLevelSecurity(stuInParam, stuOutParam)
            if self.loginID != 0:
                self.LoginFlag = True
                self.Prompt.setText('准备就绪——已连接')
                self.setWindowTitle('实时监视(RealPlay)-在线(OnLine)')
                self.login_btn.setText('断开')
                self.play_btn.setEnabled(True)
                self.play_btn.setText("监视(Play)")
                for i in range(int(device_info.nChanNum)):
                    self.Channel_comboBox.addItem(str(i))
                self.StreamTyp_comboBox.setEnabled(True)
                self.PlayMode_comboBox.setEnabled(True)
                # self.printTimer()
            else:
                QMessageBox.about(self, '提示(prompt)', error_msg+'\n'+'请重试')
        else:
            if self.playID:
                self.LoginFlag = True
                self.sdk.StopRealPlayEx(self.playID)
                self.play_btn.setText("监视(Play)")
                self.playID = 0
                self.PlayWnd.repaint()
                if 0 == self.PlayMode_comboBox.currentIndex():
                    self.sdk.SetDecCallBack(self.freePort, None)
                    self.sdk.Stop(self.freePort)
                    self.sdk.CloseStream(self.freePort)
                    self.sdk.ReleasePort(self.freePort)

            result = self.sdk.Logout(self.loginID)
            if result:
                self.LoginFlag = False
                self.SnapFreTmp = -1
                self.setWindowTitle("实时监视(RealPlay)-离线(OffLine)")
                self.login_btn.setText("连接")
                self.Prompt.setText('准备就绪———请连接到设备')
                self.loginID = 0
                self.play_btn.setEnabled(False)
                self.StreamTyp_comboBox.setEnabled(False)
                self.PlayMode_comboBox.setEnabled(False)
                self.Channel_comboBox.clear()

    def login_out_btn_onclick(self):
        reply = QMessageBox.warning(self,'提示','确认要退出吗？',QMessageBox.Yes|QMessageBox.No,QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.LoginFlag = False
            # 如果此时自动检测程序还开启，退出时应该讲tmp值设为-1，使其不满足条件，从而关闭定时器
            self.SnapFreTmp = -1
            self.close()
            ShareInfo.MyLogin = MyLogin()
            ShareInfo.MyLogin.show()
            print('已注销')
        else:
            return

    def play_btn_onclick(self):
        if not self.playID:
            if 1 == self.PlayMode_comboBox.currentIndex():
                channel = self.Channel_comboBox.currentIndex()
                if self.StreamTyp_comboBox.currentIndex() == 0:
                    stream_type = SDK_RealPlayType.Realplay
                else:
                    stream_type = SDK_RealPlayType.Realplay_1
                self.playID = self.sdk.RealPlayEx(self.loginID, channel, self.PlayWnd.winId(), stream_type)
                if self.playID != 0:
                    self.play_btn.setText("停止(Stop)")
                    self.StreamTyp_comboBox.setEnabled(False)
                    self.PlayMode_comboBox.setEnabled(False)
                else:
                    QMessageBox.about(self, '提示(prompt)', self.sdk.GetLastErrorMessage())
            else:
                result, self.freePort = self.sdk.GetFreePort()
                if not result:
                    pass
                self.sdk.OpenStream(self.freePort)
                self.sdk.Play(self.freePort, self.PlayWnd.winId())

                channel = self.Channel_comboBox.currentIndex()
                if self.StreamTyp_comboBox.currentIndex() == 0:
                    stream_type = SDK_RealPlayType.Realplay
                else:
                    stream_type = SDK_RealPlayType.Realplay_1
                self.playID = self.sdk.RealPlayEx(self.loginID, channel, 0, stream_type)
                if self.playID != 0:
                    self.play_btn.setText("停止(Stop)")
                    self.StreamTyp_comboBox.setEnabled(False)
                    self.PlayMode_comboBox.setEnabled(False)
                    self.sdk.SetRealDataCallBackEx2(self.playID, self.m_RealDataCallBack, None, EM_REALDATA_FLAG.RAW_DATA)
                    self.sdk.SetDecCallBack(self.freePort, self.m_DecodingCallBack)
        else:
            result = self.sdk.StopRealPlayEx(self.playID)
            if result:
                self.play_btn.setText("监视(Play)")
                self.StreamTyp_comboBox.setEnabled(True)
                self.PlayMode_comboBox.setEnabled(True)
                self.playID = 0
                self.PlayWnd.repaint()
                if 0 == self.PlayMode_comboBox.currentIndex():
                    self.sdk.SetDecCallBack(self.freePort, None)
                    self.sdk.Stop(self.freePort)
                    self.sdk.CloseStream(self.freePort)
                    self.sdk.ReleasePort(self.freePort)

    # 实现断线回调函数功能
    def DisConnectCallBack(self, lLoginID, pchDVRIP, nDVRPort, dwUser):
        self.setWindowTitle("实时监视(RealPlay)-离线(OffLine)")

    # 实现断线重连回调函数功能
    def ReConnectCallBack(self, lLoginID, pchDVRIP, nDVRPort, dwUser):
        self.setWindowTitle('实时监视(RealPlay)-在线(OnLine)')

    # 拉流回调函数功能
    def RealDataCallBack(self, lRealHandle, dwDataType, pBuffer, dwBufSize, param, dwUser):
        if lRealHandle == self.playID:
            # data_buffer = cast(pBuffer, POINTER(c_ubyte * dwBufSize)).contents
            # with open('./data.dav', 'ab+') as data_file:
            #     data_file.write(data_buffer)
            self.sdk.InputData(self.freePort, pBuffer, dwBufSize)

    # PLAYSDK解码回调函数功能
    def DecodingCallBack(self, nPort, pBuf, nSize, pFrameInfo, pUserData, nReserved2):
        # here get YUV data, pBuf is YUV data IYUV/YUV420 ,size is nSize, pFrameInfo is frame info with height, width.
        data = cast(pBuf, POINTER(c_ubyte * nSize)).contents
        info = pFrameInfo.contents
        # info.nType == 3 is YUV data,others ard audio data.
        # you can parse YUV420 data to RGB
        if info.nType == 3:
            pass

    # 关闭主窗口时清理资源
    def closeEvent(self, event):
        event.accept()
        if  self.loginID:
            self.sdk.Logout(self.loginID)
        self.sdk.Cleanup()

if __name__ == '__main__':
    # QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    app = QApplication(sys.argv)
    # my_wnd = MyMainWindow()
    # my_wnd.show()

    ShareInfo.MyLogin = MyLogin()
    ShareInfo.MyLogin.show()
    sys.exit(app.exec_())
